package com.avengers.core.kit;

import com.avengers.core.exception.PagingHandlerStopException;
import com.avengers.core.model.AbstractEnhancerModel;
import com.avengers.core.model.DbColumn;
import com.jfinal.plugin.activerecord.Page;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.List;

/**
 * @author yu.wang
 * @since 2018-04-05 下午2:58
 */
public abstract class AbstractPagingListHandler<M extends AbstractEnhancerModel<M>> {
    private static final Logger logger = LoggerFactory.getLogger(AbstractPagingListHandler.class);
    private static final int MAX = 1000;

    private final Integer pageSize;
    private final M condition;
    private final Boolean pageIncrease;
    private boolean shutdown;

    protected AbstractPagingListHandler(M condition) {
        this(MAX, condition, true);
    }

    protected AbstractPagingListHandler(M condition, boolean pageIncrease) {
        this(MAX, condition, pageIncrease);
    }

    protected AbstractPagingListHandler(int pageSize, M condition, boolean pageIncrease) {
        this.pageSize = pageSize;
        this.condition = condition;
        this.pageIncrease = pageIncrease;
        this.shutdown = false;
    }

    public void start(DbColumn... columns) {
        int pageNumber = 1;
        Page<M> page;
        do {
            page = paginate(pageNumber, columns);
            try {
                if (null != page && !page.getList().isEmpty()) {
                    logger.info("handler-batch table {} result size : {}", condition.getFinalTableName(), page.getList().size());
                    handle(page.getList());
                }
            } catch (PagingHandlerStopException e) {
                handleException(e, page);
                break;
            } catch (Exception e) {
                handleException(e, page);
            }
            if (pageIncrease) {
                pageNumber++;
            }
            logger.info("handler-batch {} {} {}", shutdown, null == page ? null : page.isLastPage(), null == page ? null : page.getTotalPage());
        } while (!shutdown && null != page && !page.isLastPage() && page.getTotalPage() > 0);
    }

    private Page<M> paginate(int pageNumber, DbColumn... columns) {
        if (null != condition) {
            logger.info("paginate {} condition_{}, pageNumber_{}, pageSize_{}", condition.getFinalTableName(), condition.toConditionSql(), pageNumber, pageSize);
            return condition.paginate(pageNumber, pageSize, false, columns);
        }
        return null;
    }

    /**
     * 列表处理
     *
     * @param mList 数据库查询列表
     */
    protected abstract void handle(List<M> mList);

    /**
     * 异常处理
     *
     * @param throwable 异常
     * @param mPage     数据库查询分页数据
     */
    protected abstract void handleException(Throwable throwable, Page<M> mPage);

    public void shutdown() {
        this.shutdown = true;
    }
}
